package com.wqiuqiu.gulimall.ware.service.impl;

import com.wqiuqiu.common.constant.WareConstant;
import com.wqiuqiu.common.to.es.HasWareTo;
import com.wqiuqiu.gulimall.ware.entity.WareOrderTaskDetailEntity;
import com.wqiuqiu.gulimall.ware.entity.WareOrderTaskEntity;
import com.wqiuqiu.gulimall.ware.exception.WareException;
import com.wqiuqiu.gulimall.ware.service.WareInfoService;
import com.wqiuqiu.gulimall.ware.service.WareOrderTaskService;
import com.wqiuqiu.gulimall.ware.vo.OrderLockVo;
import com.wqiuqiu.gulimall.ware.vo.WareSkuLockVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wqiuqiu.common.PageUtils;
import com.wqiuqiu.common.Query;

import com.wqiuqiu.gulimall.ware.dao.WareSkuDao;
import com.wqiuqiu.gulimall.ware.entity.WareSkuEntity;
import com.wqiuqiu.gulimall.ware.service.WareSkuService;
import org.springframework.transaction.annotation.Transactional;


@Slf4j
@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {


    @Autowired
    WareOrderTaskService wareOrderTaskService;
    @Autowired
    WareSkuService wareSkuService;
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<WareSkuEntity> wrapper = new QueryWrapper<>();
        String skuId = (String) params.get("skuId");
        String wareId = (String) params.get("wareId");
        /**
         * skuId:
         * wareId: 2
         */
        if (StringUtils.isNotEmpty(skuId)) {
            wrapper.eq("sku_id", skuId);
        }
        if (StringUtils.isNotEmpty(wareId)) {
            wrapper.eq("ware_id", wareId);
        }
        IPage<WareSkuEntity> page = this.page(
                new Query<WareSkuEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public void updateWare(List<WareSkuEntity> wareSkuEntities) {
        List<WareSkuEntity> newWare = new ArrayList<>();
        List<WareSkuEntity> oldWare = new ArrayList<>();
        for (WareSkuEntity wareSkuEntity : wareSkuEntities) {
            if (this.getOne(new QueryWrapper<WareSkuEntity>().eq("sku_id", wareSkuEntity.getSkuId())
                    .eq("ware_id", wareSkuEntity.getWareId())) == null) {
                //不存在这样的库存记录，则需要新建
                newWare.add(wareSkuEntity);
            } else {
                oldWare.add(wareSkuEntity);
            }
        }
        if (newWare.size() != 0) {
            this.saveBatch(newWare);
        }
        if (oldWare.size() != 0) {
            this.baseMapper.updateWareBatch(oldWare);
        }
    }

    @Override
    public List<HasWareTo> getWarebySkuIds(List<Long> skuIds) {
        List<HasWareTo> hasWareTos = skuIds.stream().map(obj -> {
            HasWareTo hasWareTo = new HasWareTo();
            hasWareTo.setSkuId(obj);
            Long stock = baseMapper.getWarebySkuId(obj);
            if (stock == null) {
                // TODO 如果这里没有库存信息，stock=null，会导致后面转化报NULL ERROR
                hasWareTo.setStock(0L);
            } else {
                hasWareTo.setStock(stock);
            }
            return hasWareTo;
        }).collect(Collectors.toList());
        return hasWareTos;
    }


    @Transactional
    @Override
    public boolean orderLock(WareSkuLockVo wareSkuLockVo) {

        //创建工作单，一笔订单会对应多个工作单
        List<WareOrderTaskEntity> wareOrderTaskEntities = new ArrayList<>();
        List<WareOrderTaskDetailEntity> wareOrderTaskDetailEntities = new ArrayList<>();

        List<OrderLockVo> locks = wareSkuLockVo.getLocks();
        for (OrderLockVo lock : locks) {
            //先找出sku所在的全部仓库
            Long skuId = lock.getSkuId();
            Integer count = lock.getCount();
            List<WareSkuEntity> skuEntities = this.list(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId));
            boolean locked = false;
            for (WareSkuEntity ware : skuEntities) {
                //TODO 单个仓库的锁，不能两个仓库一起锁，一个商品锁不成功都不行  这里将数据库表wms_ware_order_task 合并到了wms_ware_order
                Long num = baseMapper.lockOrder(skuId, count, ware.getWareId());
                if (num != 0) {
                    locked = true;
                    //成功，记录所库存信息,在哪个仓库锁,哪个商品锁了几件
                    WareOrderTaskEntity wareOrderTaskEntity = new WareOrderTaskEntity();
                    wareOrderTaskEntity.setWareId(ware.getWareId());
                    wareOrderTaskEntity.setOrderSn(wareSkuLockVo.getOrderSn());
                    wareOrderTaskEntity.setTaskStatus(WareConstant.OrderStatus.NEWBUILD.getCode());
                    wareOrderTaskEntity.setSkuId(lock.getSkuId());
                    wareOrderTaskEntity.setSkuNum(lock.getCount());
                    wareOrderTaskEntities.add(wareOrderTaskEntity);
                    break;
                }
            }
            if (!locked) {
                throw new WareException(skuId);
            }
        }
        wareOrderTaskService.saveBatch(wareOrderTaskEntities);
        rabbitTemplate.convertAndSend("ware-event-exchange","ware.lock.ware",wareSkuLockVo);
        log.info(wareSkuLockVo.getOrderSn() + "库存锁定成功。。。");
        return true;

    }

    @Override
    public void unlockOrder(String orderSn) {
        //修改工作单
        List<WareSkuEntity> wareSkuEntities = new ArrayList<>();
        List<WareOrderTaskEntity> orderTaskEntitys = wareOrderTaskService.list(new QueryWrapper<WareOrderTaskEntity>()
                .eq("order_sn", orderSn));
        for (WareOrderTaskEntity orderTaskEntity : orderTaskEntitys) {
            //防止重复修改
            if (orderTaskEntity.getTaskStatus() == WareConstant.OrderStatus.CANCEL.getCode())
                continue;
            Long wareId = orderTaskEntity.getWareId();
            Long skuId = orderTaskEntity.getSkuId();
            Integer skuNum = orderTaskEntity.getSkuNum();
            WareSkuEntity one = wareSkuService.getOne(new QueryWrapper<WareSkuEntity>()
                    .eq("ware_id", wareId).eq("sku_id", skuId));

            one.setStockLocked(one.getStockLocked() - skuNum);
            wareSkuEntities.add(one);
            orderTaskEntity.setTaskStatus(WareConstant.OrderStatus.CANCEL.getCode());
        }
        if (!orderTaskEntitys.isEmpty())
            wareOrderTaskService.updateBatchById(orderTaskEntitys);
        if (!wareSkuEntities.isEmpty())
            wareSkuService.updateBatchById(wareSkuEntities);
    }

}